#!/usr/bin/python

#imports
try:
	import math
	import libtcodpy as libtcod
except ImportError, err:
	print 'could not load module. %s' %(err)

#defines
DEV_MODE = True
SCREEN_WIDTH = 40
SCREEN_HEIGHT = 60
LIMIT_FPS = 60

CLEAR = libtcod.Color(255, 0, 255)
WHITE = libtcod.Color(204, 204, 204)
BLACK = libtcod.Color(0, 0, 0)
BLUE = libtcod.Color(74, 74, 255)
YELLOW = libtcod.Color(248, 191, 43)
RED = libtcod.Color(248, 0, 0)


#classes

class Generator:
	def __init__(self):
		global shot, shot_select
		shot_select = 0
		libtcod.namegen_parse('data/names.cfg')
		shot = [Weapon(libtcod.namegen_generate('weapons')), Weapon(libtcod.namegen_generate('weapons')), Weapon(libtcod.namegen_generate('weapons'))]

class Input:

	def handle_global_keys(self):
		global key
		key = libtcod.console_check_for_keypress()

		#alt+enter: toggle fullscreen
		if key.vk == libtcod.KEY_ENTER and key.lalt:
			libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
		#escape: exit game
		elif key.vk == libtcod.KEY_ESCAPE:
			return True

	def handle_room_keys(self):
		global key, shot_select
		#player movement
		if libtcod.console_is_key_pressed(libtcod.KEY_LEFT) and libtcod.console_is_key_pressed(libtcod.KEY_UP):
			player.speed = 15
			player.degrees = 225
		elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT) and libtcod.console_is_key_pressed(libtcod.KEY_UP):
			player.speed = 15
			player.degrees = 315
		elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT) and libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
			player.speed = 15
			player.degrees = 135
		elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT) and libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
			player.speed = 15
			player.degrees = 45
		elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT):
			player.speed = 15
			player.degrees = 180
		elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT):
			player.speed = 15	
			player.degrees = 0
		elif libtcod.console_is_key_pressed(libtcod.KEY_UP):
			player.speed = 15
			player.degrees = 270
		elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
			player.speed = 15
			player.degrees = 90
		else:
			player.speed = 0
		#keep pliayer within room
		if player.x <= 1:
			player.x = 0.99
		if player.x >= SCREEN_WIDTH - 1:
			player.x = SCREEN_WIDTH - 1
		if player.y <= 1:
			player.y = 0.99
		if player.y >= SCREEN_HEIGHT - 1:
			player.y = SCREEN_HEIGHT - 1
		#player shooting
		if key.vk == libtcod.KEY_SPACE:
			objects.append(Object(player.x, player.y - 1, '*', YELLOW, 20, 270))
		if key.c == ord('1'):
			shot_select = 0
		if key.c == ord('2'):
			shot_select = 1
		if key.c == ord('3'):
			shot_select = 2

class Logic:
	def begin_frame(self):
		for i in objects:
			i.update()
	
	def move_all(self):
		for i in objects:
			i.move()
				
	def cleanup_all(self):
		for i in objects:
			if i.x < 0 or i.x > SCREEN_WIDTH or i.y < 0 or i.y > SCREEN_HEIGHT:
				objects.remove(i)
 
class Graphics:
	def __init__(self):
		global bg_image, consoles, bg, fg, ui, dev
		bg_image = libtcod.image_load('data/bg.png')
		bg = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
		fg = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
		ui = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
		dev = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
		consoles = [bg, fg, ui, dev]

	def clear_all(self):
		global consoles
		for i in  consoles:
			libtcod.console_set_key_color(i, CLEAR)
			libtcod.console_set_background_color(i, CLEAR)
			libtcod.console_set_background_flag(i, libtcod.BKGND_SET)
			libtcod.console_clear(i)

	def render_bg(self):
		global bg_image, bg
		libtcod.image_blit_2x(bg_image, bg, 0, 0)
		libtcod.console_blit(bg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 1.0, 1.0)

	def render_fg(self):
		global fg
		for i in objects:
			i.draw()
		libtcod.console_blit(fg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 1.0, 0.0)

	def render_ui(self):
		global ui, shot, shot_select
		libtcod.console_set_foreground_color(ui, RED)
		libtcod.console_set_background_color(ui, RED)
		libtcod.console_rect(ui, 1, SCREEN_HEIGHT - 5, 14, 4, True, libtcod.BKGND_SET)
		libtcod.console_print(ui, 1, SCREEN_HEIGHT - 5, 'S\nH\nO\nT')
		libtcod.console_set_foreground_color(ui, RED * 0.66)
		libtcod.console_print(ui, 2, SCREEN_HEIGHT - 5, '%c\n%c\n%c\n%c' %(libtcod.CHAR_VLINE, libtcod.CHAR_VLINE, libtcod.CHAR_VLINE, libtcod.CHAR_VLINE))
		if shot_select == 0:
			x = 1.0
		else:
			x = 0.66
		libtcod.console_set_foreground_color(ui, RED * x)
		libtcod.console_print(ui, 3, SCREEN_HEIGHT - 5, '%c %cL\n   V\n%c %c' %(libtcod.CHAR_NW, libtcod.CHAR_NE, libtcod.CHAR_SW, libtcod.CHAR_SE))
		if shot_select == 1:
			x = 1.0
		else:
			x = 0.66
		libtcod.console_set_foreground_color(ui, RED * x)
		libtcod.console_print(ui, 7, SCREEN_HEIGHT - 5, '%c %cL\n   V\n%c %c' %(libtcod.CHAR_NW, libtcod.CHAR_NE, libtcod.CHAR_SW, libtcod.CHAR_SE))
		if shot_select == 2:
			x = 1.0
		else:
			x = 0.66
		libtcod.console_set_foreground_color(ui, RED * x)
		libtcod.console_print(ui, 11, SCREEN_HEIGHT - 5, '%c %cL\n   V\n%c %c' %(libtcod.CHAR_NW, libtcod.CHAR_NE, libtcod.CHAR_SW, libtcod.CHAR_SE))
		libtcod.console_set_foreground_color(ui, RED)
		libtcod.console_print(ui, 3, SCREEN_HEIGHT - 2, '%s' %shot[shot_select].name)
		libtcod.console_blit(ui, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 1.0, 0.25)

	def render_dev(self):
		global dev, shot_select
		if DEV_MODE:
			object_count = 0
			for i in objects:
				object_count += 1
			libtcod.console_set_foreground_color(dev, WHITE)
			libtcod.console_set_background_color(dev, BLACK)
			libtcod.console_print(dev, 0, 0, 'fps: %d' %libtcod.sys_get_fps())
			libtcod.console_print(dev, 0, 1, 'objects: %d' %object_count)
			libtcod.console_print(dev, 0, 2, 'step: %d' %game.step)
		libtcod.console_blit(dev, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 1.0, 0.25)

	def render_all(self):
		self.clear_all()
		self.render_bg()
		self.render_fg()
		self.render_ui()
		self.render_dev()
		libtcod.console_flush()

class Object:
	def __init__(self, x, y, char, color, speed, degrees, events = {}):
		self.x = x
		self.y = y
		self.char = char
		self.color = color
		self.speed = speed
		self.adj_speed = 0
		self.degrees = degrees
		self.radians = math.radians(self.degrees)
		self.events = events
		self.step = 0
		self.time_prev = 0
		self.time_now = int(libtcod.sys_elapsed_seconds())
		exec self.events.get('init', '')

	def update(self):
		self.radians = math.radians(self.degrees)
		self.adj_speed = self.speed * libtcod.sys_get_last_frame_length()
		self.advance_step()

	def move(self):
		self.y += self.adj_speed * math.sin(self.radians)
		self.x += self.adj_speed * math.cos(self.radians)

	def draw(self):
		global fg
		libtcod.console_set_foreground_color(fg, self.color)
		libtcod.console_set_background_color(fg, BLACK)
		libtcod.console_put_char(fg, int(self.x), int(self.y), self.char, libtcod.BKGND_SET)

	def advance_step(self):
		self.time_now = int(libtcod.sys_elapsed_milli())
		if self.time_now > self.time_prev:
			self.step += 1
			exec self.events.get(self.step, '')
		self.time_prev = self.time_now

class Weapon:
	def __init__(self, name):
		self.name = name

#initialization
libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'shmuprl', False)
libtcod.sys_set_fps(LIMIT_FPS)

objects = []
player = Object(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, '@', WHITE, 0, 0)
objects.append(player)
game = Object(0, 0, '', CLEAR, 0, 0)
generator = Generator()
logic = Logic()
graphics = Graphics()
input = Input()

#main loop
while not libtcod.console_is_window_closed():

	#handle graphics
	logic.begin_frame()
	graphics.render_all()

	#handle input
	if input.handle_global_keys():
		break
	input.handle_room_keys()

	#handle logic
	logic.move_all()
	logic.cleanup_all()
	game.advance_step()
